#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <cstdio>
#include <queue>

using namespace std;
const int CAPACITY_MAX = 8;
template <typename T>
class BlockQueue
{
private:
    bool IsEmpty()
    {
        return _q.empty();
    }
    bool IsFull()
    {
        return _q.size() >= CAPACITY_MAX;
    }

public:
    BlockQueue(int capacity = CAPACITY_MAX)
        : _capacity(capacity), _p_sleep_num(0), _c_sleep_num(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_full_queue, nullptr);
        pthread_cond_init(&_empty_queue, nullptr);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_full_queue);
        pthread_cond_destroy(&_empty_queue);
    }

    void EnQueue(const T &data)
    {
        pthread_mutex_lock(&_mutex);
        while (IsFull())
        {
            _p_sleep_num++;
            printf("生产者进入休眠,_p_sleep_num: %d\n",_p_sleep_num);
            pthread_cond_wait(&_full_queue, &_mutex);
            _p_sleep_num--;
        }
        _q.push(data);
        if (_c_sleep_num > 0)
        {
            pthread_cond_signal(&_empty_queue);
            printf("唤醒消费者...\n");
        }
        pthread_mutex_unlock(&_mutex);
    }
    T Pop()
    {
        pthread_mutex_lock(&_mutex);
        while (IsEmpty())
        {
            _c_sleep_num++;
            printf("消费者进入休眠,_c_sleep_num: %d\n",_c_sleep_num);

            pthread_cond_wait(&_empty_queue, &_mutex);
            _c_sleep_num--;
        }
        T data = _q.front();
        _q.pop();
        printf("消费了一个数据data:%d\n",data);
        if (_p_sleep_num > 0)
        {
            pthread_cond_signal(&_full_queue);
            printf("唤醒生产者...\n");
        }
        pthread_mutex_unlock(&_mutex);
      

        return data;
    }

private:
    queue<T> _q;
    int _capacity;
    pthread_mutex_t _mutex;
    pthread_cond_t _full_queue;
    pthread_cond_t _empty_queue;
    int _p_sleep_num;
    int _c_sleep_num;
};
